package com.redijedi.tapestry5.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

import com.redijedi.tapestry5.TreeNodeModel;

/**
 * @author torr
 * 
 */
public class TreeNodeModelWrapper implements TreeNodeModel {

	private final String _id;

	private final Object _value;

	private final List<TreeNodeModelWrapper> _children;

	private final Map<String, String> _attributes;

	private TreeNodeModelWrapper _parent;

	private Queue<TreeRenderAction> _preActions = new LinkedList<TreeRenderAction>();

	private Queue<TreeRenderAction> _postActions = new LinkedList<TreeRenderAction>();

	/**
	 * Recursively builds this TreeNodeModel graph.
	 * 
	 * @param model
	 */
	public TreeNodeModelWrapper(TreeNodeModel model) {
		_id = model.getId();
		_value = model.getValue();
		_children = new ArrayList<TreeNodeModelWrapper>();
		for (TreeNodeModel m : model.getChildren()) {
			TreeNodeModelWrapper w = new TreeNodeModelWrapper(m);
			w.setParent(this);
			_children.add(w);
		}
		if (model.getAttributes() != null) {
			_attributes = Collections.unmodifiableMap(model.getAttributes());
		} else {
			_attributes = null;
		}
	}

	void setActions() {
		// determine the rendering actions this node should phave performed on
		// it. it should have at least 2 actions for post and pre-render steps.
		if (_parent == null || _children.size() > 0) {
			_preActions.add(TreeRenderAction.OPEN_CONTAINER);
			_preActions.add(TreeRenderAction.CLOSE_CONTAINER);
		}
	}

	public Map<String, String> getAttributes() {
		return _attributes;
	}

	public String getId() {
		return _id;
	}

	public Object getValue() {
		return _value;
	}

	public Iterable<TreeNodeModelWrapper> getChildren() {
		return _children;
	}

	void setParent(TreeNodeModelWrapper parent) {
		_parent = parent;
	}

	TreeNodeModelWrapper getParent() {
		return _parent;
	}

	TreeRenderAction getPreRenderAction() {
		TreeRenderAction action = _preActions.poll();
		return action == null ? TreeRenderAction.DO_NOTHING : action;
	}

	TreeRenderAction getPostRenderAction() {
		TreeRenderAction action = _postActions.poll();
		return action == null ? TreeRenderAction.DO_NOTHING : action;
	}

	@Override
	public String toString() {
		return String.format("TreeNodeModel[%s]", _id);
	}
}
